# __setitem__方法：设置键值对时检查key是否为字符串类型，如果不是则抛出KeyError异常，否则打印设置信息并调用父类方法设置值。
# __getitem__方法：获取值时如果key不存在则打印提示信息并返回默认值0，否则返回实际值。
class MyDict(dict):
    def __setitem__(self, key, value):
        if not isinstance(key, str):
            raise KeyError("key must be a string")
        print(f"设置 {key} = {value}")
        super().__setitem__(key, value)

    def __getitem__(self, key):
        if key not in self:
            print(f"{key} 不存在，返回默认 0")
            return 0
        return super().__getitem__(key)


"""
列表的标识主要是以下特殊方法：
len：返回容器长度，支持 len() 函数
getitem：支持索引访问，如 obj[index]
setitem：支持索引赋值，如 obj[index] = value
__delitem__：支持删除元素，如 del obj[index]
__iter__：支持迭代，使对象可被 for 循环遍历
__reversed__：支持反向迭代
__contains__：支持成员测试，如 item in obj
这些方法共同构成了Python序列协议，使对象具备类似列表的行为特征。当一个类实现了这些方法，它就可以像列表一样使用索引、切片、迭代等操作
"""

"""
字典的标识主要是以下特殊方法：
getitem：支持键值访问，如 obj[key]
setitem：支持键值赋值，如 obj[key] = value
__delitem__：支持删除键值对，如 del obj[key]
len：返回字典长度，支持 len() 函数
__iter__：支持迭代键，使对象可被 for 循环遍历
__contains__：支持成员测试，如 key in obj
keys()、values()、items()：返回字典的键、值、键值对视图
这些方法共同构成了Python映射协议，使对象具备类似字典的行为特征，可以使用键值对存储和访问数据。
"""

# setitem：使对象支持 obj[key] = value 语法
# getitem：使对象支持 obj[key] 语法
d = MyDict()
d["a"] = 10
# d[3] = 30
print(d["a"])
print(d["b"])
# print(d[3])

d = {"a": 10, "b": 20, 3: 30}
print(d["a"])
print(d["b"])
print(d[3])
d["a"] = 11
print(d["a"])
for k, v in d.items():
    print(k, v)

myDict = MyDict(d)
print(myDict["a"])
print(myDict["b"])
print(myDict[3])
